package com.anjiplus.template.gaea.auth.modules.gaeaannot.service.impl;

import com.alibaba.fastjson.JSON;
import com.anji.plus.gaea.constant.Enabled;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anji.plus.gaea.holder.UserContentHolder;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.controller.dto.AnnotSendReadDTO;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.controller.dto.GaeaAnnouncementDTO;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.controller.param.GaeaAnnouncementSendParam;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.controller.param.ServiceMsgRequest;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.dao.GaeaAnnouncementMapper;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.dao.GaeaAnnouncementSendMapper;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.dao.entity.GaeaAnnouncement;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.dao.entity.GaeaAnnouncementSend;
import com.anjiplus.template.gaea.auth.modules.gaeaannot.service.GaeaAnnouncementService;
import com.anjiplus.template.gaea.auth.modules.user.dao.GaeaUserMapper;
import com.anjiplus.template.gaea.auth.modules.user.dao.entity.GaeaUser;
import com.anjiplus.template.gaea.auth.modules.websocket.WebSocketService;
import com.anjiplus.template.gaea.auth.modules.websocket.dto.UserMsgDto;
import com.anjiplus.template.gaea.common.MagicValueConstants;
import com.anjiplus.template.gaea.common.enums.RelationTypeEnums;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 系统公告信息表(GaeaAnnouncement)ServiceImpl
 *
 * @author peiyanni
 * @since 2021-03-29 15:17:22
 */
@Service
public class GaeaAnnouncementServiceImpl implements GaeaAnnouncementService {
    @Autowired
    private GaeaAnnouncementMapper gaeaAnnouncementMapper;
    @Autowired
    private GaeaUserMapper gaeaUserMapper;
    @Autowired
    private GaeaAnnouncementSendMapper gaeaAnnouncementSendMapper;
    @Autowired
    private WebSocketService webSocketService;

    @Override
    public GaeaBaseMapper<GaeaAnnouncement> getMapper() {
        return gaeaAnnouncementMapper;
    }

    @Override
    public Boolean saveAndPublishAnnotOne(GaeaAnnouncementDTO annotDto) {
        GaeaAnnouncement gaeaAnnouncement = new GaeaAnnouncement();
        BeanUtils.copyProperties(annotDto, gaeaAnnouncement);
        gaeaAnnouncement.setSendStatus(Enabled.YES.getValue());
        gaeaAnnouncement.setSendTime(new Date());
        gaeaAnnouncement.setPublisher(UserContentHolder.getContext().getUsername());
        gaeaAnnouncementMapper.insert(gaeaAnnouncement);
        //判断是否全体用户
        List<String> userNameList = null;
        if ("ALL".equals(annotDto.getMsgType())) {
            //查询所有有效用户
            List<GaeaUser> userList = gaeaUserMapper.getAllUser();
            if (!CollectionUtils.isEmpty(userList)) {
                userNameList = userList.stream().map(e -> e.getUsername()).collect(Collectors.toList());
            }
        } else if (StringUtils.isNotBlank(annotDto.getUserNames())) {
            //如果是指定用户
            userNameList = Arrays.asList(annotDto.getUserNames().split(","));
        }
        List<UserMsgDto> batchUserMsgDtoList = new ArrayList<>();
        saveAnnotSendInfo(batchUserMsgDtoList, gaeaAnnouncement, userNameList);
        //对接websocket 实时发送消息
        webSocketService.sendMessage(batchUserMsgDtoList);
        return true;
    }

    @Override
    @Transactional
    public Boolean publishAnnotBatch(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return true;
        }
        List<GaeaAnnouncement> list = gaeaAnnouncementMapper.selectBatchIds(ids);
        if (CollectionUtils.isEmpty(list)) {
            return true;
        }
        List<GaeaAnnouncement> filterList = list.stream().filter(e -> 0 == e.getSendStatus()).collect(Collectors.toList());
        //查询需要发送全部用户的公告
        List<GaeaAnnouncement> filterAllUserList = filterList.stream().filter(e -> MsgTypeEnum.ALL.getValue().equals(e.getMsgType())).collect(Collectors.toList());
        //查询需要发送指定用户的公告
        List<GaeaAnnouncement> filterNotAllUserList = filterList.stream().filter(e -> !MsgTypeEnum.ALL.getValue().equals(e.getMsgType())).collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(filterNotAllUserList)) {
            List<UserMsgDto> batchUserMsgDtoList = new ArrayList<>();
            for (GaeaAnnouncement annot : filterNotAllUserList) {
                if (StringUtils.isEmpty(annot.getUserNames())) {
                    continue;
                }
                List<String> userNameList = Arrays.asList(annot.getUserNames().split(","));
                saveAnnotSendInfo(batchUserMsgDtoList, annot, userNameList);
                updateAnnotStatu(annot);
            }
            //对接websocket 实时发送消息
            webSocketService.sendMessage(batchUserMsgDtoList);
        }
        if (!CollectionUtils.isEmpty(filterAllUserList)) {
            List<UserMsgDto> batchUserMsgDtoList = new ArrayList<>();
            //查询所有有效用户
            List<String> userNameList = null;
            List<GaeaUser> userList = gaeaUserMapper.getAllUser();
            if (!CollectionUtils.isEmpty(userList)) {
                userNameList = userList.stream().map(e -> e.getUsername()).collect(Collectors.toList());
            }
            for (GaeaAnnouncement annot : filterAllUserList) {
                saveAnnotSendInfo(batchUserMsgDtoList, annot, userNameList);
                updateAnnotStatu(annot);
            }
            //对接websocket 实时发送消息
            webSocketService.sendMessage(batchUserMsgDtoList);
        }

        return true;
    }

    /**
     * 保存用户系统消息记录
     * 并构建发送websocke消息
     *
     * @param batchUserMsgDtoList
     * @param annot
     * @param userNameList
     */
    private void saveAnnotSendInfo(List<UserMsgDto> batchUserMsgDtoList, GaeaAnnouncement annot, List<String> userNameList) {
        List<GaeaAnnouncementSend> sendList = convert2SendList(userNameList, annot.getId());
        //批量保存
        if (CollectionUtils.isEmpty(sendList)) {
            return;
        }
        List<UserMsgDto> userMsgDtoList = sendList.stream().map(e -> {
            gaeaAnnouncementSendMapper.insert(e);
            UserMsgDto msgDto = null;
            if (StringUtils.isNotEmpty(annot.getRelationInfo())) {
                msgDto = new UserMsgDto(e.getId().toString(), annot.getTitle(), e.getUserName(),annot.getRelationInfo(), RelationTypeEnums.valueOf(annot.getRelationType()));
            } else {
                msgDto = new UserMsgDto(e.getId().toString(), annot.getTitle(), e.getUserName(),annot.getId().toString(),RelationTypeEnums.SYSTEM);
            }
            return msgDto;
        }).collect(Collectors.toList());
        batchUserMsgDtoList.addAll(userMsgDtoList);
        sendList.clear();
    }

    @Override
    public Page<AnnotSendReadDTO> queryMyAnnotList(GaeaAnnouncementSendParam param) {
        Page<AnnotSendReadDTO> page = new Page<>(param.getPageNumber(), param.getPageSize());
        param.setUsername(UserContentHolder.getContext().getUsername());
        List<AnnotSendReadDTO> list = gaeaAnnouncementSendMapper.myAnnotReadList(page, param);
        page.setRecords(list);
        return page;
    }

    @Override
    @Transactional
    public Boolean cancelAnnot(Long id) {
        GaeaAnnouncement gaeaAnnot = gaeaAnnouncementMapper.selectById(id);
        gaeaAnnot.setCancelTime(new Date());
        gaeaAnnot.setSendStatus(MagicValueConstants.TWO);
        gaeaAnnouncementMapper.updateById(gaeaAnnot);

        LambdaQueryWrapper<GaeaAnnouncementSend> sendLambdaQueryWrapper = Wrappers.lambdaQuery();
        sendLambdaQueryWrapper.eq(GaeaAnnouncementSend::getAnntId, id);
        gaeaAnnouncementSendMapper.delete(sendLambdaQueryWrapper);
        return true;
    }

    /**
     * 发送业务及时消息给用户
     * 1.新增系统消息信息
     * 2.新增消息发送记录表信息
     * 3.websocket发送消息给用户
     *
     * @param msgRequest
     * @return
     */
    @Override
    @Transactional
    public Boolean sendServiceMsg(ServiceMsgRequest msgRequest) {
        GaeaAnnouncement gaeaAnnouncement = new GaeaAnnouncement();
        BeanUtils.copyProperties(msgRequest, gaeaAnnouncement);
        if(StringUtils.isEmpty(msgRequest.getPriority())){
            gaeaAnnouncement.setPriority("M");
        }
        if(null!=msgRequest.getRelationData()){
            gaeaAnnouncement.setRelationInfo(JSON.toJSONString(msgRequest.getRelationData()));
        }
        gaeaAnnouncement.setMsgCategory(MagicValueConstants.STRING_TWO);
        gaeaAnnouncement.setMsgType(MsgTypeEnum.USER.getValue());
        gaeaAnnouncement.setSendStatus(Enabled.YES.getValue());
        gaeaAnnouncement.setSendTime(new Date());
        gaeaAnnouncementMapper.insert(gaeaAnnouncement);
        List<UserMsgDto> batchUserMsgDtoList = new ArrayList<>();
        List<String> userNameList = Arrays.asList(msgRequest.getUserNames().split(","));
        saveAnnotSendInfo(batchUserMsgDtoList, gaeaAnnouncement, userNameList);
        //对接websocket 实时发送消息
        webSocketService.sendMessage(batchUserMsgDtoList);
        return true;
    }


    /**
     * 组装系统公告阅读记录信息
     *
     * @param userNameList
     * @param annotId
     * @return
     */
    private List<GaeaAnnouncementSend> convert2SendList(List<String> userNameList, Long annotId) {
        if (CollectionUtils.isEmpty(userNameList)) {
            return null;
        }
        List<GaeaAnnouncementSend> sendList = userNameList.stream().map(e -> {
            GaeaAnnouncementSend gaeaAnnotSend = new GaeaAnnouncementSend();
            gaeaAnnotSend.setAnntId(annotId);
            gaeaAnnotSend.setReadFlag(MagicValueConstants.ZERO);
            gaeaAnnotSend.setUserName(e);
            return gaeaAnnotSend;
        }).collect(Collectors.toList());
        return sendList;
    }

    /**
     * 系统公告状态变更
     *
     * @param annot
     */
    public void updateAnnotStatu(GaeaAnnouncement annot) {
        annot.setSendStatus(Enabled.YES.getValue());
        annot.setSendTime(new Date());
        annot.setPublisher(UserContentHolder.getContext().getUsername());
        gaeaAnnouncementMapper.updateById(annot);
    }

    public enum MsgTypeEnum {
        USER("USER"), ALL("ALL");
        private String value;

        MsgTypeEnum(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}